package com.niiwoo.civet.trade.service.local.contract;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.niiwoo.civet.account.constant.PlateformConstant;
import com.niiwoo.civet.account.dto.response.AccountCompanyDTO;
import com.niiwoo.civet.account.service.AccountCompanyDubboService;
import com.niiwoo.civet.trade.constant.AmountHandleConstant;
import com.niiwoo.civet.trade.dao.entity.FadadaContractTemplateFile;
import com.niiwoo.civet.trade.dao.entity.Project;
import com.niiwoo.civet.trade.dao.entity.ProjectContract;
import com.niiwoo.civet.trade.dao.entity.ProjectRate;
import com.niiwoo.civet.trade.dao.mapper.AdvanceConfigMapperExt;
import com.niiwoo.civet.trade.dao.mapper.ProjectRateMapperExt;
import com.niiwoo.civet.trade.dto.request.loan.RepaymentPlanDTO;
import com.niiwoo.civet.trade.enums.PeriodUnitEnum;
import com.niiwoo.civet.trade.enums.ProjectFeeChargeNodeEnum;
import com.niiwoo.civet.trade.enums.RepaymentTypeEnum;
import com.niiwoo.civet.trade.service.local.contract.vo.InvestorContractDTO;
import com.niiwoo.civet.trade.service.local.plan.BorrowerInvestorRepaymentContext;
import com.niiwoo.civet.trade.utils.SysNumberUtil;
import com.niiwoo.civet.user.dto.request.SimpleOrgInfo;
import com.niiwoo.civet.user.service.OrganizationDubboService;
import com.niiwoo.civet.user.service.UserAuthorizationInfoDubboService;
import com.niiwoo.civet.user.service.UserIdentityDubboService;
import com.niiwoo.tripod.base.component.PrivacyMasks;
import com.niiwoo.tripod.fadada.dto.request.GenerateContractRequestDTO;
import com.niiwoo.tripod.fadada.dto.request.GenerateContractRequestDTO.DynamicTable;
import com.niiwoo.tripod.fadada.dto.response.FadadaResponseDTO;
import com.niiwoo.tripod.fadada.enums.SignClientRoleEnum;
import com.niiwoo.tripod.provider.exception.BizException;
import com.niiwoo.tripod.service.component.SnowflakeIdWorker;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.MathContext;
import java.util.*;

/**
 * 鸿特-企业居间借款合同
 * 
 * @author liaojunjun
 *
 */
@Service
public class OrgCompanyFastLoanContract extends AbstractFadadaContract {
	
	private static final Logger logger = LoggerFactory.getLogger(OrgCompanyFastLoanContract.class);

	@Autowired
	private SnowflakeIdWorker snowflakeIdWorker;

	@Reference(version = "1.0.0")
	private UserIdentityDubboService userIdentityDubboService;

	@Reference(version = "1.0.0")
	private UserAuthorizationInfoDubboService userAuthorizationInfoDubboService;
	
	@Reference(version = "1.0.0")
	private OrganizationDubboService organizationDubboService;

	@Autowired
	private PrivacyMasks privacyMasks;
	
	@Value("${platform.caCertId}")
	private String platformCaCertId;

	@Autowired
	private BorrowerInvestorRepaymentContext borrowerInvestorRepaymentContext;

	@Autowired
	private ProjectRateMapperExt projectRateMapperExt;

	@Autowired
	AdvanceConfigMapperExt advanceConfigMapperExt;

	@Reference(version = "1.0.0")
	private AccountCompanyDubboService accountCompanyDubboService;
	@Autowired
	private ContractBaseService contractBaseService;
	
	@Override
	public ProjectContract contractHandler(FadadaContractTemplateFile contractTemplate, String bizContractNo,
										   Project project, String userId) throws Exception{
		logger.info("鸿特-企业借款合同处理开始... projectId:{}", project.getProjectId());
		String contractId = snowflakeIdWorker.nextId() + "";
		SimpleOrgInfo borrowOrg = organizationDubboService.getByOrgId(project.getBorrowUserId());

		SimpleOrgInfo guarantee = organizationDubboService.getByOrgId(project.getGuaranteeCompanyOrgId());
		if(guarantee == null){
			logger.error("鸿特-企业借款合同处理异常 guarantee is null. projectId:{},orgId:{}, project.getGuaranteeCompanyOrgId:{}", project.getProjectId(), project.getOrgId(), JSON.toJSON(project.getGuaranteeCompanyOrgId()));
			throw new BizException("TRD10005", "鸿特-企业借款合同处理异常 guarantee is null");
		}
		AccountCompanyDTO accountCompanyByBusinessLicense = accountCompanyDubboService.getAccountCompanyByBusinessLicense(project.getConsultingBusinessLicense());
		if(accountCompanyByBusinessLicense == null){
			logger.error("鸿特-企业借款合同处理异常 informationConsultantOrg is null. projectId:{}, consultingBusinessLicense:{}", project.getProjectId(), project.getConsultingBusinessLicense());
			throw new BizException("TRD10005", "鸿特-企业借款合同处理异常 informationConsultantOrg is null");
		}
		SimpleOrgInfo informationConsultantOrg = organizationDubboService.getByOrgId(accountCompanyByBusinessLicense.getUserId());
		if(informationConsultantOrg == null){
			logger.error("鸿特-企业借款合同处理异常 informationConsultantOrg is null. projectId:{}, AccountCompanyDTO:{}", project.getProjectId(), JSON.toJSON(accountCompanyByBusinessLicense));
			throw new BizException("TRD10005", "鸿特-企业借款合同处理异常 informationConsultantOrg is null");
		}

		this.generateContract(contractTemplate, contractId, bizContractNo, project, contractBaseService.getInvestUserInfo(project.getProjectId()), guarantee, borrowOrg, informationConsultantOrg);

		ProjectContract result = this.signContract(contractTemplate, contractId, project, contractBaseService.getInvestUserInfo(project.getProjectId()), guarantee, borrowOrg, informationConsultantOrg);

		this.contractFilling(contractId);
		logger.info("鸿特-企业借款合同处理结束... projectId:{}", project.getProjectId());
		return result;
	}

	private void generateContract(FadadaContractTemplateFile contractTemplate, String contractId, String bizContractNo,
			Project project, List<InvestorContractDTO> projectInvestOrderList, SimpleOrgInfo guarantee, SimpleOrgInfo borrowOrg, SimpleOrgInfo informationConsultantOrg) throws Exception{
		logger.info("鸿特-企业借款合同生成开始... projectId:{}", project.getProjectId());

		GenerateContractRequestDTO dto = new GenerateContractRequestDTO();

		dto.setContractId(contractId);
		dto.setDocTitle(contractTemplate.getTemplateName());
		dto.setTemplateId(contractTemplate.getTemplateId());

		Map<String, String> parameterMap = new HashMap<String, String>();

		parameterMap.put("contractNo", bizContractNo);
		parameterMap.put("repaymentTypeName", RepaymentTypeEnum.enumOf(project.getRepaymentType()).getDesc());
		parameterMap.put("borrowerName", "乙方（借款人）： ".concat(borrowOrg.getOrganizationName())); // 借款人
		parameterMap.put("borrowerIdCard", "统一社会信用代码/营业执照编号： ".concat(privacyMasks.maskInstitutionalReditCode(StringUtils.isBlank(borrowOrg.getUnifiedSocialCreditCode()) ? borrowOrg.getCharterCode() : borrowOrg.getUnifiedSocialCreditCode())));
		parameterMap.put("borrowEmail", "电子邮箱： " + borrowOrg.getEmail());
		parameterMap.put("borrowAgentRealName", "联系人： " + borrowOrg.getRepresentative());
		parameterMap.put("borrowAgentIdentityCard", "身份证号码： " + (StringUtils.isNoneBlank(borrowOrg.getLegalPersonCertNumber()) ? privacyMasks.maskIdCard(privacyMasks.decryptPrivacy(borrowOrg.getLegalPersonCertNumber())) : ""));
		parameterMap.put("borrowAgentPhoneNumber", "联系方式： " + (StringUtils.isNoneBlank(borrowOrg.getLegalPersonPhoneNumber()) ? privacyMasks.decryptPrivacy(borrowOrg.getLegalPersonPhoneNumber()) : ""));
		parameterMap.put("borrowerAddress", "地址： ".concat((StringUtils.isBlank(borrowOrg.getAddress())) ? project.getLoanProvince().concat(project.getLoanCity()).concat(project.getLoanArea()) : borrowOrg.getAddress()));

		parameterMap.put(
				"borrowAmount",
				project.getContractAmount()
						.setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN).toString()); // 借款金额
		parameterMap.put("capitalAmount", SysNumberUtil.amountChineseFormat(project.getContractAmount().toString())); // 大写借款金额
		parameterMap.put("deadLine", project.getDeadline() + "");// 借款期限
		parameterMap.put("projectTitle", project.getTitle().replaceAll("借款用途：","").replaceAll("借款用于",""));
		
		Date lastRepaymentDate = null;
		BigDecimal platformManagerFeeYear = BigDecimal.ZERO;
		BigDecimal guaranteeRateYear = BigDecimal.ZERO;
		BigDecimal consultantFeeYear = BigDecimal.ZERO;
		PeriodUnitEnum periodUnitEnum = PeriodUnitEnum.enumOf(project.getDeadlineUnit());
		BigDecimal beforeManageRate = project.getBeforeManageRate() == null ? BigDecimal.ZERO : project.getBeforeManageRate();
		switch (periodUnitEnum) {
		case MONTH:
			lastRepaymentDate = DateUtils.addDays(DateUtils.addMonths(project.getFullSuccessTime(), project.getDeadline()), -1);

			platformManagerFeeYear = project.getManageRate().add(beforeManageRate).multiply(new BigDecimal(AmountHandleConstant.HUNDRED)).divide(BigDecimal.valueOf(project.getDeadline()),
					MathContext.DECIMAL128).multiply(new BigDecimal(AmountHandleConstant.YEAR_OF_MONTH)).setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);

			guaranteeRateYear = project.getGuaranteeRate().multiply(new BigDecimal(AmountHandleConstant.HUNDRED)).divide(BigDecimal.valueOf(project.getDeadline()),
					MathContext.DECIMAL128).multiply(new BigDecimal(AmountHandleConstant.YEAR_OF_MONTH)).setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);

			consultantFeeYear = project.getConsultingRate().multiply(new BigDecimal(AmountHandleConstant.HUNDRED)).divide(BigDecimal.valueOf(project.getDeadline()),
					MathContext.DECIMAL128).multiply(new BigDecimal(AmountHandleConstant.YEAR_OF_MONTH)).setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);
			break;

		case DAY:
			lastRepaymentDate = DateUtils.addDays(project.getFullSuccessTime(), project.getDeadline());

			platformManagerFeeYear = project.getManageRate().add(beforeManageRate).multiply(new BigDecimal(AmountHandleConstant.HUNDRED)).divide(BigDecimal.valueOf(project.getDeadline()),
					MathContext.DECIMAL128).multiply(new BigDecimal(AmountHandleConstant.YEAR_OF_DAY)).setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);

			guaranteeRateYear = project.getGuaranteeRate().multiply(new BigDecimal(AmountHandleConstant.HUNDRED)).divide(BigDecimal.valueOf(project.getDeadline()),
					MathContext.DECIMAL128).multiply(new BigDecimal(AmountHandleConstant.YEAR_OF_DAY)).setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);

			consultantFeeYear = project.getConsultingRate().multiply(new BigDecimal(AmountHandleConstant.HUNDRED)).divide(BigDecimal.valueOf(project.getDeadline()),
					MathContext.DECIMAL128).multiply(new BigDecimal(AmountHandleConstant.YEAR_OF_DAY)).setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);
			break;

		default:
			break;
		}

		parameterMap.put("lastRepaymentYear", DateFormatUtils.format(lastRepaymentDate, "yyyy"));
		parameterMap.put("lastRepaymentMonth", DateFormatUtils.format(lastRepaymentDate, "MM"));
		parameterMap.put("lastRepaymentDay", DateFormatUtils.format(lastRepaymentDate, "dd"));

		parameterMap.put("investRate", project.getBorrowRate().multiply(new BigDecimal(AmountHandleConstant.HUNDRED))
				.setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN).toString());// 借款年利率
		parameterMap.put("borrowPenaltyRate", project.getPenaltyRate().multiply(new BigDecimal(AmountHandleConstant.HUNDRED))
				.setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN).toString()); // 借款逾期罚息日率

		parameterMap.put("companyGuarantee", guarantee.getOrganizationName());// 担保公司
		parameterMap.put("companyGuaranteeReditCode", privacyMasks.maskInstitutionalReditCode(StringUtils.isBlank(guarantee.getUnifiedSocialCreditCode()) ? guarantee.getCharterCode() : guarantee.getUnifiedSocialCreditCode()));// 担保公司机构信用代码
		parameterMap.put("companyGuaranteeEmail", guarantee.getEmail());

		parameterMap.put("informationConsultantName", informationConsultantOrg.getOrganizationName());// 咨询信息方
		parameterMap.put("informationConsultantReditCode", privacyMasks.maskInstitutionalReditCode(StringUtils.isBlank(informationConsultantOrg.getUnifiedSocialCreditCode()) ? informationConsultantOrg.getCharterCode() : informationConsultantOrg.getUnifiedSocialCreditCode()));// 咨询信息方信用代码
		parameterMap.put("informationConsultantAddress", informationConsultantOrg.getAddress());
		
		parameterMap.put("niiwooReditCode", privacyMasks.maskInstitutionalReditCode(PlateformConstant.NIIWOO_REDIT_CODE));
		//parameterMap.put("niiwooAddress", "广东省深圳市南山区科技园北区乌石头路8号天明科技大厦主楼11楼、12楼1202室");

		// 平台管理费
		BigDecimal beforeManageFee = project.getBeforeManageFee() == null ? BigDecimal.ZERO : project.getBeforeManageFee();
		BigDecimal platformManageFeeTotal = project.getManageFee().add(beforeManageFee);
		parameterMap.put("platformManagerFee", platformManageFeeTotal.toString());
		parameterMap.put("capitalPlatformManagerFee", SysNumberUtil.amountChineseFormat(platformManageFeeTotal.toString()));
		parameterMap.put("platformManagerFeeYear",platformManagerFeeYear.toString());
		parameterMap.put("beforeManageFee", beforeManageFee.toString());
		parameterMap.put("capitalBeforeManagerFee", SysNumberUtil.amountChineseFormat(beforeManageFee.toString()));
		parameterMap.put("manageFee", project.getManageFee().toString());
		parameterMap.put("capitalManageFee", SysNumberUtil.amountChineseFormat(project.getManageFee().toString()));

		// 担保服务费
		BigDecimal guaranteeServiceFeeTotal = project.getContractAmount().multiply(project.getGuaranteeRate())
				.setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);
		parameterMap.put("guaranteeServiceFee", guaranteeServiceFeeTotal.toString());
		parameterMap.put("capitalGuaranteeServiceFee", SysNumberUtil.amountChineseFormat(guaranteeServiceFeeTotal.toString()));
		parameterMap.put("guaranteeRateYear",guaranteeRateYear.toString());
		parameterMap.put("guaranteeFeeChargeNode",project.getGuaranteeFeeChargeNode().toString());

		// 咨询服务费
		BigDecimal firstYearConsultingFee = BigDecimal.ZERO;
		BigDecimal secondYearConsultingFee = BigDecimal.ZERO;
		BigDecimal thirdYearConsultingFee = BigDecimal.ZERO;
		BigDecimal lendConsultingFee = project.getBeforeSeekAdviceServiceFee();
		BigDecimal consultantFee = project.getBeforeSeekAdviceServiceFee().add(project.getConsultingFee())
				.setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);
		if(ProjectFeeChargeNodeEnum.AfterSeekAdviceServiceFeeChargeNode.COLLECTION_OF_MONEY.getValue().equals(project.getAfterSeekAdviceServiceFeeChargeNode())){
			lendConsultingFee = lendConsultingFee.add(project.getConsultingFee());
		}else {
			List<ProjectRate> projectRateList = projectRateMapperExt
					.queryProjectRateListOrderByCurrentPeriodAscByProjectIdAndBorrowUserId(project.getProjectId(), project.getBorrowUserId());
			for(ProjectRate projectRate : projectRateList){
				if(projectRate.getCurrentPeriod() > 0 && projectRate.getCurrentPeriod() <= 12){
					firstYearConsultingFee = firstYearConsultingFee.add(projectRate.getAfterSeekAdviceServiceFeeRate());
				}else if(projectRate.getCurrentPeriod() > 12 && projectRate.getCurrentPeriod() <= 24){
					secondYearConsultingFee = secondYearConsultingFee.add(projectRate.getAfterSeekAdviceServiceFeeRate());
				}else if(projectRate.getCurrentPeriod() > 24 && projectRate.getCurrentPeriod() <= 36){
					thirdYearConsultingFee = thirdYearConsultingFee.add(projectRate.getAfterSeekAdviceServiceFeeRate());
				}
			}
			firstYearConsultingFee = project.getContractAmount().multiply(firstYearConsultingFee)
					.setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);
			secondYearConsultingFee = project.getContractAmount().multiply(secondYearConsultingFee)
					.setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);
			thirdYearConsultingFee = project.getContractAmount().multiply(thirdYearConsultingFee)
					.setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);
		}
		parameterMap.put("totalConsultingFee", consultantFee.toString());
		parameterMap.put("capitalTotalConsultingFee", SysNumberUtil.amountChineseFormat(consultantFee.toString()));
		parameterMap.put("lendConsultingFee", lendConsultingFee.toString());
		parameterMap.put("capitalLendConsultingFee", SysNumberUtil.amountChineseFormat(lendConsultingFee.toString()));
		parameterMap.put("firstYearConsultingFee", firstYearConsultingFee.toString());
		parameterMap.put("capitalFirstYearConsultingFee", SysNumberUtil.amountChineseFormat(firstYearConsultingFee.toString()));
		parameterMap.put("secondYearConsultingFee", secondYearConsultingFee.toString());
		parameterMap.put("capitalSecondYearConsultingFee", SysNumberUtil.amountChineseFormat(secondYearConsultingFee.toString()));
		parameterMap.put("thirdYearConsultingFee", thirdYearConsultingFee.toString());
		parameterMap.put("capitalThirdYearConsultingFee",SysNumberUtil.amountChineseFormat(thirdYearConsultingFee.toString()));
		//parameterMap.put("consultantFeeYear",consultantFee.toString());

		List<RepaymentPlanDTO> repaymentPlanDTOList = borrowerInvestorRepaymentContext.getBorrowerRepaymentPlan(
				RepaymentTypeEnum.enumOf(project.getRepaymentType()), project.getContractAmount(), project.getBorrowRate(),
				project.getDeadline(), PeriodUnitEnum.enumOf(project.getDeadlineUnit()),
				project.getFullSuccessTime() == null ? new Date() : project.getFullSuccessTime(), project.getLeastCalculateInterestDays());

		BigDecimal interestTotal = BigDecimal.ZERO;
		for (RepaymentPlanDTO repaymentPlanDTO : repaymentPlanDTOList) {
			interestTotal = interestTotal.add(repaymentPlanDTO.getInterest());
		}

		BigDecimal payTotal = interestTotal.add(platformManageFeeTotal).add(guaranteeServiceFeeTotal).add(consultantFee);

		// 总支出上限
		parameterMap.put("payTotal",payTotal.toString());
		parameterMap.put("capitalPayTotal",SysNumberUtil.amountChineseFormat(payTotal.toString()));
		//借款人综合资金成本费率计算公式为：（利息 +平台管理费 +担保服务费） /借款金额 /借款期限 *12
		BigDecimal payTotalRateYear =  payTotal.divide(project.getContractAmount(), MathContext.DECIMAL128)
				.divide(BigDecimal.valueOf(project.getDeadline()), MathContext.DECIMAL128)
				.multiply(new BigDecimal((PeriodUnitEnum.MONTH.equals(periodUnitEnum) ? AmountHandleConstant.YEAR_OF_MONTH : AmountHandleConstant.YEAR_OF_DAY )))
				.multiply(new BigDecimal(AmountHandleConstant.HUNDRED))
				.setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);
		parameterMap.put("payTotalRateYear",payTotalRateYear.toString());

		parameterMap.put("beginYear", DateFormatUtils.format(project.getFullSuccessTime(), "yyyy"));
		parameterMap.put("beginMonth", DateFormatUtils.format(project.getFullSuccessTime(), "MM"));
		parameterMap.put("beginDay", DateFormatUtils.format(project.getFullSuccessTime(), "dd"));
		
		parameterMap.put("signDate", DateFormatUtils.format(new Date(), "yyyy年MM月dd日"));

		// 投资人姓名列表
		List<List<String>> invNameList = new ArrayList<>();
		// 投资详情列表
		List<List<String>> invInvestInfoList = new ArrayList<>();
		// 投资人签名
		List<List<String>> invSignatureNamesList = new ArrayList<>();

		int index = 1;

		for (InvestorContractDTO projectInvestOrder : projectInvestOrderList) {
			// 投资人姓名
			String invNameText = "                甲方" + contractBaseService.toChinese(index) + "(出借人)：" + projectInvestOrder.getInvestUserName() + "\n"
					           + "                身份证号/统一社会信用代码/营业执照编号：    " + privacyMasks.maskIdCardSixTwo(Byte.valueOf("1").equals(projectInvestOrder.getInvestorType()) ? privacyMasks.decryptPrivacy(projectInvestOrder.getInvestorIdCard()) : projectInvestOrder.getInvestorIdCard());
			List<String> invNameCells = new ArrayList<>();
			invNameCells.add(invNameText);
			invNameList.add(invNameCells);

			// 投资人投资信息信息
			String invInvestInfoText = "                甲方" + contractBaseService.toChinese(index) + ":" + "￥"
					+ projectInvestOrder.getInvestAmount() + "元  大写："
					+ SysNumberUtil.amountChineseFormat(projectInvestOrder.getInvestAmount().toString());
			List<String> invInvestInfoCells = new ArrayList<>();
			invInvestInfoCells.add(invInvestInfoText);
			invInvestInfoList.add(invInvestInfoCells);

			// 签章信息
			String invSignatureNamesText = "                甲方" + contractBaseService.toChinese(index) + "（签章）：" + projectInvestOrder.getInvestUserName()
					+ "," + privacyMasks.maskIdCardSixTwo(Byte.valueOf("1").equals(projectInvestOrder.getInvestorType()) ? privacyMasks.decryptPrivacy(projectInvestOrder.getInvestorIdCard()) : projectInvestOrder.getInvestorIdCard());

			List<String> invSignatureNamesCells = new ArrayList<>();
			invSignatureNamesCells.add(invSignatureNamesText);
			invSignatureNamesList.add(invSignatureNamesCells);
			index++;
		}

		// 签章信息
		String borrowerSignatureNamesText = "                乙方（签章）：" + borrowOrg.getOrganizationName() + ","
				+ privacyMasks.maskInstitutionalReditCode(StringUtils.isBlank(borrowOrg.getUnifiedSocialCreditCode()) ? borrowOrg.getCharterCode() : borrowOrg.getUnifiedSocialCreditCode());
		List<String> borrowerSignatureNamesCells = new ArrayList<>();
		borrowerSignatureNamesCells.add(borrowerSignatureNamesText);
		invSignatureNamesList.add(borrowerSignatureNamesCells);

		// 签章信息
		String companySignatureNamesText = "                丙方（签章）：" + guarantee.getOrganizationName();
		List<String> companySignatureNamesCells = new ArrayList<>();
		companySignatureNamesCells.add(companySignatureNamesText);
		invSignatureNamesList.add(companySignatureNamesCells);

		// 签章信息
		String platformSignatureNamesText = "                丁方（签章）：深圳市你我金融信息服务有限公司";
		List<String> platformSignatureNamesCells = new ArrayList<>();
		platformSignatureNamesCells.add(platformSignatureNamesText);
		invSignatureNamesList.add(platformSignatureNamesCells);

		// 签章信息
		String informationConsultantSignatureNamesText = "                戊方（签章）：" + informationConsultantOrg.getOrganizationName();
		List<String> informationConsultantSignatureNamesCells = new ArrayList<>();
		informationConsultantSignatureNamesCells.add(informationConsultantSignatureNamesText);
		invSignatureNamesList.add(informationConsultantSignatureNamesCells);

		// 投资人姓名列表
		// 表格header
		List<String> headers = new ArrayList<>();
		headers.add("");

		DynamicTable investNameTable = new DynamicTable();

		investNameTable.setInsertWay(1);
		investNameTable.setKeyword("合同编号");
		investNameTable.setCellHeight(30f);
		investNameTable.setHeaders(headers);
		investNameTable.setBorderFlag(false);
		investNameTable.setDatas(invNameList);

		DynamicTable investInfoTable = new DynamicTable();
		// investInfoTable.put("pageBegin",5);
		investInfoTable.setInsertWay(1);
		investInfoTable.setKeyword("各主体具体出借金额如下");
		investInfoTable.setCellHeight(30f);
		investInfoTable.setHeaders(headers);
		investInfoTable.setBorderFlag(false);
		investInfoTable.setDatas(invInvestInfoList);

		DynamicTable signNameTable = new DynamicTable();
		signNameTable.setInsertWay(1);
		signNameTable.setKeyword("该一定期限由你我金融制定。");
		signNameTable.setCellHeight(60f);
		signNameTable.setHeaders(headers);
		signNameTable.setCellVerticalAlignment(5);
		signNameTable.setDatas(invSignatureNamesList);
		signNameTable.setBorderFlag(false);

		List<DynamicTable> tables = new ArrayList<DynamicTable>();
		tables.add(investNameTable);
		tables.add(investInfoTable);
		tables.add(signNameTable);

		dto.setDynamicTables(tables);
		dto.setParameterMap(parameterMap);

		generateContract(dto);
		logger.info("鸿特-企业借款合同生成结束... projectId:{}", project.getProjectId());
	}

	private ProjectContract signContract(FadadaContractTemplateFile contractTemplate, String contractId,
			Project project, List<InvestorContractDTO> projectInvestOrderList, SimpleOrgInfo guarantee, SimpleOrgInfo borrowOrg, SimpleOrgInfo informationConsultantOrg) throws Exception{
		String METHOD_NAME = "法大大合同自动签署-满标借款合同 projectId:" + project.getProjectId();
		logger.info(METHOD_NAME);

		String transactionId = null;
		String docTitle = project.getBorrowUserName() + "的借款合同_" + contractId;

		FadadaResponseDTO fadadaResponse = null;
		logger.info("法大大合同自动签署-满标借款合同 投资人签署开始... projectId:{}", project.getProjectId());
		// 投资人签署
		int index = 1;
		for (InvestorContractDTO projectInvestOrder : projectInvestOrderList) {
			transactionId = snowflakeIdWorker.nextId() + "";
			String investorCaCertId = projectInvestOrder.getFadadaCacertId();
			String investorSignKeyword = "甲方" + contractBaseService.toChinese(index) + "（签章）："
					+ projectInvestOrder.getInvestUserName();
			fadadaResponse = extSignAuto(transactionId, contractId, investorCaCertId,
					SignClientRoleEnum.INVESTOR.getValue(), docTitle, investorSignKeyword);
			index++;
		}
		logger.info("法大大合同自动签署-满标借款合同 投资人签署结束... projectId:{}", project.getProjectId());

		// 担保公司签署 
		transactionId = snowflakeIdWorker.nextId() + "";
		String guaranteeCaCertId = guarantee.getFadadaCacertId();
		String guaranteeSignKeyword = "丙方（签章）：" + guarantee.getOrganizationName();
		fadadaResponse = extSignAuto(transactionId, contractId, guaranteeCaCertId,
				SignClientRoleEnum.GUARANTEE.getValue(), docTitle, guaranteeSignKeyword);
		logger.info("法大大合同自动签署-满标借款合同担保公司签署结束... projectId:{}", project.getProjectId());
		// 借款人签署
		transactionId = snowflakeIdWorker.nextId() + "";
		String borrowerCaCertId = borrowOrg.getFadadaCacertId();
		String borrowerSignKeyword = "乙方（签章）：" + borrowOrg.getOrganizationName();
		fadadaResponse = extSignAuto(transactionId, contractId, borrowerCaCertId,
				SignClientRoleEnum.BORROWER.getValue(), docTitle, borrowerSignKeyword);
		logger.info("法大大合同自动签署-满标借款合同 借款人签署结束... projectId:{}", project.getProjectId());
		// 平台公章
		transactionId = snowflakeIdWorker.nextId() + "";
		String platformSignKeyword = "丁方（签章）：深圳市你我金融信息服务有限公司";
		fadadaResponse = extSignAuto(transactionId, contractId, platformCaCertId,
				SignClientRoleEnum.PLATFORM.getValue(), docTitle, platformSignKeyword);
		logger.info("法大大合同自动签署-满标借款合同 平台签署结束... projectId:{}", project.getProjectId());
		// 咨询方签章
		transactionId = snowflakeIdWorker.nextId() + "";
		String informationConsultantCaCertId = informationConsultantOrg.getFadadaCacertId();
		String informationConsultantSignatureNamesText = "戊方（签章）：" + informationConsultantOrg.getOrganizationName();
		fadadaResponse = extSignAuto(transactionId, contractId, informationConsultantCaCertId,
				SignClientRoleEnum.GUARANTEE.getValue(), docTitle, informationConsultantSignatureNamesText);
		logger.info("法大大合同自动签署-满标借款合同 咨询方签署结束... projectId:{}", project.getProjectId());
		return this.buildContractUpdateRecord(contractTemplate.getTemplateId(), contractId, transactionId,
				fadadaResponse.getViewUrl(), fadadaResponse.getDownloadUrl());
	}

}
